import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Escenario principal del videojuego en el cual se agregaran, eliminan y se
 * comunican los objetos del juego.
 * 
 * @author Asael Hernández García 
 * @version (a version number or a date)
 */
public class PistaAutomovil extends World
{
    private Obstaculo auto1, auto2, auto3, auto4, auto5;
    private Jugador jugador;
    private Pista pista;
    private Linea linea;
    private Civil civil;
    private Bache bache;
    private Aceite aceite;
    private Roca roca;
    private Gasolina gas;
    private Herramienta herr;
    private Patrulla police;
    private Camello camel;
    private Leon leon;
    private Counter countDamage;
    private Counter gasCounter;
    private Counter distancia;
    private Counter velocidad;
    private Counter levelCounter;
    private Pause pause;
    private GreenfootSound fondoSound;
    private boolean advertencia;
    private int nivel, dist, constDist, damage, random;
    private UserRecords records;
   
    /**Constructor dle mundo
     * @String bgImage recibe el nombre de la imagen que mostrara el escenario
     * @int dist establece la distancia para pasar al siguiente nivel
     * @int tiempo establece el tiempo en el que aprecen los obstaculos
     */
    public PistaAutomovil(String bgImage, int dist, int damage, int random)
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(900, 564, 1); 
        this.damage = damage;
        this.random = random;
        this.dist = dist; 
        constDist = dist;
        records = new UserRecords();
        nivel = 0;
        advertencia = false;
        fondoSound = new GreenfootSound("fondo.mp3");
        auto1 = new Obstaculo1(damage);
        auto2 = new Obstaculo2(damage*2);
        auto3 = new Obstaculo3(damage*3);
        auto4 = new Obstaculo4(damage*2);
        auto5 = new Obstaculo5(damage);
        pause = new Pause();
        pista = new Pista();
        civil = new Civil();
        bache = new Bache();
        roca = new Roca();
        aceite = new Aceite();
        gas = new Gasolina();
        herr = new Herramienta();
        camel = new Camello();
        leon = new Leon();
        jugador = new Jugador(dist);
        addObject(jugador, 443, 362);
        addObject(pista, 450,283);
        addObject(pause, getWidth() - pause.getImage().getWidth()/2, pause.getImage().getHeight()/2);
        velocidad = new Counter("Velocidad: ");
        velocidad.setValue(1);
        addObject(velocidad, 500, 15);
        countDamage = new Counter("Daño: ");
        addObject(countDamage, 50, 15);
        gasCounter = new Counter("Gasolina: ");
        gasCounter.setValue(100);
        addObject(gasCounter, 200, 15);
        distancia = new Counter("Distancia: ");
        addObject(distancia,360,15);
        levelCounter = new Counter("Nivel: ");
        levelCounter.setValue(1);
        addObject(levelCounter,620,15);
        fondoSound.setVolume(50);
        Greenfoot.setSpeed(50);
        setBackground(bgImage);
        setPaintOrder(Boton.class,Label.class,Patrulla.class, Jugador.class,Obstaculo.class,Bonificacion.class,Obstaculos.class,Linea.class,Pista.class);
    }
    
    public void act()
    {
        genObs();
        checkLevel();
        
        if(!fondoSound.isPlaying())
            fondoSound.playLoop();
        if(distancia.getValue() >= dist){
            nivel++;
            if(nivel==6){
                int puntosDist = distancia.getValue();
                int puntosDamage = countDamage.getValue();
                int puntos = puntosDist * puntosDamage;
                records.guardaRecords(puntos);
                ganaste();
            }  
        }
        
        if(countDamage.getValue() >= 100){
           int puntosDist = distancia.getValue();
           int puntosDamage = countDamage.getValue();
           int puntos = puntosDist * puntosDamage;
           records.guardaRecords(puntos);
           perdiste("TU AUTO SE AVERIO");
        }
        if(gasCounter.getValue() <= 0){
            int puntosDist = distancia.getValue();
            int puntosDamage = countDamage.getValue();
            int puntos = puntosDist * puntosDamage;
            records.guardaRecords(puntos);
            perdiste("NO HAY GASOLINA");
        }
    }
    
    /** Método para verificar el nivel actual del juego y definir comportamientos para nuevos niveles
     * 
     */
    public void checkLevel()
    {
        if (nivel==2){
            setBackground("L2.png");
            dist = constDist*2;
            damage = damage*2;
            random = 900;
            levelCounter.setValue(2);
        }
        if (nivel==3){
            setBackground("L3.png");
            dist = constDist*3;
            damage = damage*3;
            random = 800;
            levelCounter.setValue(3);
        }
        if (nivel==4){
            setBackground("L4.png");
            dist = constDist*4;
            damage = damage*4;
            random = 700;
            levelCounter.setValue(4);
        }
        if (nivel==5){
            setBackground("L5.png");
            dist = constDist*5;
            damage = damage*5;
            random = 600;
            levelCounter.setValue(5);
        }
        
    }
    
    /**Método para generar aleatoriamente un obstáculo en el juego
     * 
     */
    public void genObs()
    {
        switch(Greenfoot.getRandomNumber(random))
        {
            case 1: if(getObjects(Obstaculo.class).isEmpty())
                        addObst(auto1);
                    break;
            case 2: if(getObjects(Obstaculo.class).isEmpty())
                        addObst(auto2);
                    break;
            case 3: if(getObjects(Obstaculo.class).isEmpty())
                        addObst(auto3);
                    break;
            case 4: if(getObjects(Obstaculo.class).isEmpty())
                        addObst(auto4);
                    break;
            case 5: if(getObjects(Obstaculo.class).isEmpty())
                        addObst(auto5);
                    break;         
        }
        
        switch(Greenfoot.getRandomNumber(random - 300)){
            case 6: if(getObjects(Obstaculos.class).isEmpty())
                        addObst(civil);
                    break;
            case 7: if(getObjects(Obstaculos.class).isEmpty())
                        addObst(bache);
                    break;
            case 10:if(getObjects(Obstaculos.class).isEmpty())
                        addObst(aceite);
                    break;
            case 11:if(getObjects(Obstaculos.class).isEmpty())
                        addObst(roca);
                    break;
            case 12:if(getObjects(Obstaculos.class).isEmpty())
                        addObst(leon);
                    break;
            case 13:if(getObjects(Obstaculos.class).isEmpty())
                        addObst(camel);
                    break;
        }
        
        switch(Greenfoot.getRandomNumber(random - 100)){
             case 1: if(getObjects(Bonificacion.class).isEmpty())
                         addObst(gas);
                          break;
             case 2: if(getObjects(Bonificacion.class).isEmpty())
                        addObst(herr);
                        break;
        }
    }
    
    /** Método para agregar un obstáculo en el borde inferior de la pantalla
    *   @param objeto objeto que se va a agregar al mundo
    */
    public void addObst(Object objeto)
    {
        if(objeto instanceof Obstaculo)
            addObject((Obstaculo)objeto, 20+ Greenfoot.getRandomNumber(getWidth()-40) , getHeight());
        if(objeto instanceof Civil)
            addObject((Civil)objeto, 0 , getHeight()-200);
        if(objeto instanceof Leon)
            addObject((Leon)objeto, 0 , getHeight()-230);
        if(objeto instanceof Camello)
            addObject((Camello)objeto, getWidth() , getHeight()-250);
        if(objeto instanceof Obstaculos)
            addObject((Obstaculos)objeto, 20+ Greenfoot.getRandomNumber(getWidth()-40) , getHeight());
        if(objeto instanceof Bonificacion)
            addObject((Bonificacion)objeto, 20+ Greenfoot.getRandomNumber(getWidth()-40) , getHeight());
        
    }
    
    /** Método para desaparecer el obstaculo automovil del escenario 
     * @param object objeto que sera eliminado del mundo.
     * 
     */
    public void removeObs(Object object)
    {
            if(object instanceof Obstaculo1){
                removeObject(auto1);
                auto1 = new Obstaculo1(damage);
            }
            if(object instanceof Obstaculo2){
                removeObject(auto2);
                auto2 = new Obstaculo2(damage*2);
            }
            if(object instanceof Obstaculo3){
                removeObject(auto3);
                auto3 = new Obstaculo3(damage*3);
            }
            if(object instanceof Obstaculo4){
                removeObject(auto4);
                auto4 = new Obstaculo4(damage*2);
            }
            if(object instanceof Obstaculo5){
                removeObject(auto5);
                auto5 = new Obstaculo5(damage);
            }   
            if(object instanceof Bache){
                removeObject(bache);
                bache = new Bache();
            }  
            if(object instanceof Roca){
                removeObject(roca);
                roca = new Roca();
            } 
            if(object instanceof Aceite){
                removeObject(aceite);
                aceite = new Aceite();
            }     
            if(object instanceof Herramienta){
                removeObject(herr);
                herr = new Herramienta();
            }  
            if(object instanceof Gasolina){
                removeObject(gas);
                gas = new Gasolina();
            } 
            if(object instanceof Civil){
                removeObject(civil);
                civil = new Civil();
            } 
            if(object instanceof Patrulla){
                removeObject(police);
            } 
            if(object instanceof Camello){
                removeObject(camel);
                camel = new Camello();
            }
            if(object instanceof Leon){
                removeObject(leon);
                leon = new Leon();
            } 
    }
    
    /**Método para aumentar el contador de daño del automovil del jugador
    *   @param damage cantidad que será aumentada de daño, dependiendo del obstaculo.   
    */
    public void addDamage(int damage)
    {
        countDamage.add(damage);
    }
    
    /**Método para regresar el daño del automovil del jugador
    *   @return damage cantidad que será aumentada de daño, dependiendo del obstaculo.   
    */
    public int getDamage()
    {
        return countDamage.getValue();
    }
    
    /**Método para disminuir el contador de daño del automovil del jugador
    *   @damage cantidad que será disminuida en el daño del automovil del jugador.   
    */
    public void subDamage(int damage)
    {
        if(countDamage.getValue() >= 5)
          countDamage.add(-damage);
    }
    
    /**Método para aumentar el contador de distancia recorrida del automovil del jugador
    *   @param distancia cantidad de distancia que recorre el jugador  
    *  
    */
    public void addDist(int distancia)
    {
        this.distancia.add(distancia);
    }
    
    /**Método para regresar la distancia recorrida del automovil del jugador
    *   @param distancia cantidad de distancia que recorre el jugador  
    *  
    */
    public int getDist()
    {
        return distancia.getValue();
    }
    
    /**Método para aumentar el contador de velocidad del automovil del jugador 
    *  
    */
    public void addVel()
    {
        velocidad.add(1);
    }
    
    /**Método para disminuir el contador de velocidad del automovil del jugador 
    *  
    */
    public void subVel()
    {
        velocidad.add(-1);
    }
    
    /**Método para disminuir la cantidad de gasolina del automovil
       *disminuye la gasolinaa del jugador
       */
    public void subGas()
    {
        if(gasCounter.getValue() >= 0)
            gasCounter.add(-1);
    }
    
    /**Método para aumentar la cantidad de gasolina del automovil
    *   @param gas cantidad de gasolina que se le bonificara al jugador
    *
    */
    public void addGas(int gas)
    {
        if(gasCounter.getValue() <= 95)
            gasCounter.add(gas);
    }
    
    /** Método para mandar una advertencia al civil y a los animales
    *   @param adv establece verdadero si se  manda la advertencia.
    */
    public void advertencia(boolean adv)
    {
        advertencia = adv;
    }
    
    /**@return advertencia Retorna verdadero o falso dependiendo del valor de la adrtencia
     * 
     */
    public boolean getAdv()
    {
        return advertencia;
    }
    
    /** Método para mostrar el mensaje de ganaste
     * 
     */
    public void ganaste()
    {
        Greenfoot.stop();
        Label ganaste = new Label("GANASTE",100);
        addObject(ganaste,getWidth()/2, getHeight()/2);
        Greenfoot.delay(1000);
    }
    
    /**Método para mostrar el mensaje de perdiste
     * @param msg motivo por el que perdio el jugador
     */
    public void perdiste(String msg)
    {
        fondoSound.stop();
        Label perdiste = new Label(msg,100);
        addObject(perdiste,getWidth()/2, getHeight()/2);
        Greenfoot.delay(500);
        Greenfoot.setWorld(new Menu());
        //Greenfoot.stop();
    }
    
    /** Método para agregar una patrulla al mundo
     * 
     */
    public void addPolice()
    {
        if(getObjects(Patrulla.class).isEmpty()){
            police = new Patrulla();
            addObject(police, police.getImage().getWidth() + Greenfoot.getRandomNumber(getWidth() - police.getImage().getWidth()), getHeight());
        }
    }
    
    /** Método para saber si el jugador se impacto con algun automovil
     * civil o animal
     * @return true o false dependiendo de si se estampo o no
     */
    public boolean impactoJugador()
    {
        return jugador.impacto();
    }
    
    /** Método para pausar la música de fondo del juego
     * 
     */
    public void pausarMusica()
    {
        fondoSound.pause();
    }
    
     /** Método para reproducir la música de fondo del juego
     * 
     */
    public void reanudarMusica()
    {
        fondoSound.play();
    }
        
    /** Método para regresar el nivel actual del juego
     * @return nivel contiene el nivel del juego.
     */
    public int getLevel()
    {
        return nivel;
    }    
    
    /** Método para regresar la velocidad en que se generan los obstáculos
     * @return random rango en que se generan los obstáculos
     */
    public int getRandom()
    {
        return random;
    }
}
